package api

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"goshell.straysh.com/internal/cmd"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"time"
)

type AnsibleRequest struct {
	Inventory string `json:"inventory" form:"inventory"`
	Playbook  string `json:"playbook" form:"playbook"`
	Limit     string `json:"limit" form:"limit"`
	Tags      string `json:"tags" form:"tags"`
	ListHosts string `json:"list_hosts" form:"list_hosts"`
	ListTasks string `json:"list_tasks" form:"list_tasks"`
}

func (s *AnsibleService) Playbook(c *gin.Context) {
	var req *AnsibleRequest
	if err := c.ShouldBind(&req); err != nil {
		s.log.Error("ShouldBind failed", zap.Error(err))
		c.JSON(200, gin.H{
			"code": 50001,
			"err":  err.Error(),
		})
		return
	}

	cfg := s.config.Data.Ansible
	tmpLogFile, err := s.createTmpfile(s.config.Data.Stream.LogDir, "ansible") // /app/Golang/gitee.com/goshell/goapi/runtime/2023_06_14/ansible_683870037.log
	if err != nil {
		s.log.Error("create TempLogFile failed", zap.Error(err))
		c.JSON(200, gin.H{
			"code": 50001,
			"err":  err.Error(),
		})
		return
	}
	go func() {
		defer func() {
			_, err := tmpLogFile.WriteString("__end\n")
			if err != nil {
				fmt.Println(err.Error())
			}
		}()
		// ansible-playbook -i inventory.yml book1.yml --limit all[0] --tags hostname --list-hosts --list-tasks
		args := &cmd.Argument{
			Script:  "ansible-playbook",
			Params:  s.buildArgs(req),
			WorkDir: cfg.WorkDir,
			//Envars:   []string{"BUILD_TAG=" + in.DockerTag},
			TempLogFile: tmpLogFile,
		}
		_, err = cmd.RunCommand(args)
		if err != nil {
			fmt.Printf("%+v\n", err)
		}
	}()

	parts := strings.SplitN(tmpLogFile.Name(), "/", -1) // /app/Golang/gitee.com/goshell/goapi/runtime/2023_06_14/ansible_683870037.log
	parts = parts[len(parts)-2:]                        // ["2023_06_14", "ansible_683870037.log"]

	c.JSON(200, gin.H{
		"code": 10000,
		"data": gin.H{
			"TempLogFile": path.Join(parts...),
		},
	})
}

func (s *AnsibleService) createTmpfile(logRoot string, serviceName string) (*os.File, error) {
	logDir := path.Join(logRoot, time.Now().Format("2006_01_02"))
	if _, err := os.Stat(logDir); err != nil {
		if !os.IsNotExist(err) {
			return nil, err
		}
		if err2 := os.Mkdir(logDir, 0755); err2 != nil {
			return nil, fmt.Errorf("os.Stat err->%+v, os.Mkdir err->%+v", err, err2)
		}
	}

	TempLogFile, err := ioutil.TempFile(logDir, serviceName+"_*.log")
	if err != nil {
		return nil, err
	}

	return TempLogFile, nil
}

func (s *AnsibleService) buildArgs(req *AnsibleRequest) []string {
	// ansible-playbook -i inventory.yml book1.yml --limit all[0] --tags hostname --list-hosts --list-tasks
	if req.Inventory == "" {
		req.Inventory = s.config.Data.Ansible.Inventory
	}
	if req.Playbook == "" {
		req.Playbook = s.config.Data.Ansible.Playbook
	}

	params := []string{"-i", req.Inventory, req.Playbook}
	if req.ListHosts != "" {
		params = append(params, []string{"--limit", req.ListHosts}...)
	}
	if req.Tags != "" {
		params = append(params, []string{"--tags", req.Tags}...)
	}
	if req.ListHosts != "" {
		params = append(params, []string{"--list-hosts", req.ListHosts}...)
	}
	if req.ListTasks != "" {
		params = append(params, []string{"--list-tasks", req.ListTasks}...)
	}

	return params
}
